/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package menu;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.hsqldb.lib.HashMap;

/**
 *
 * @author maurizio
 */
public class DataAccess {

    private static DataAccess instance = null;

    public synchronized static DataAccess getInstance() throws SQLException {
        if (instance == null) {
            instance = new DataAccess();
        }
        return instance;
    }

    private Connection c = null;

     private DataAccess() throws SQLException {
        try {
            Class.forName("org.hsqldb.jdbcDriver");
            c = DriverManager.getConnection("jdbc:hsqldb:file:db/menudb", "maurizio", "nonlaso");
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
     
    public HashMap tree() {
        HashMap data = new HashMap();
        ResultSet piatto,portata;
        String nPortata,nPiattoPort;
        try {
            java.sql.Statement stmt = c.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
            portata = stmt.executeQuery("select NOME from PORTATA");
            piatto= stmt.executeQuery("select piatto.nome as n_piatto, portata.nome as n_portata from ((piatto left join categoria on piatto.cod_piatto = categoria.cod_piatto) left join portata on portata.cod_portata=categoria.cod_portata) order by n_piatto");
            while (portata.next()) {
                nPortata=portata.getString("nome");// nome portata
                List piatti = new ArrayList(); // lista che conterrà i piatti associati alla portata attuale
                while (piatto.next()){
                    nPiattoPort=piatto.getString("n_portata"); //nome della portata associata al piatto
                    if (nPiattoPort.equals(nPortata)){
                        piatti.add(piatto.getString("n_piatto")); //aggiungo il piatto alla lista relativa alla portata attuale
                    }
                }
                data.put(nPortata,piatti);
                piatto.beforeFirst(); //Sposto il puntatore all'inizio della struttura dati
            }
        } catch (SQLException ex) {
            Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
        }
        return data;    
    }

    public String[] getPortata () throws SQLException{
        java.sql.Statement stmt = c.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        ResultSet portate = stmt.executeQuery("SELECT portata.nome FROM portata");
        ArrayList<String> ris = new ArrayList<String>();
        while (portate.next()){
            ris.add(portate.getString("nome"));
        }
        String[] risarray = new String [ris.size()];
        risarray=ris.toArray(risarray);
        return risarray;
    }

    public int addPortata (String portata,int posizione){
        if (!portata.isEmpty()){
            try {
                java.sql.Statement stmt = c.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
                ResultSet ctrl1=stmt.executeQuery("SELECT COUNT(*) as conto FROM portata WHERE portata.nome='"+portata+"'");
                ctrl1.next();
                if (ctrl1.getInt("conto")==0){
                    ResultSet ctrl2=stmt.executeQuery("SELECT COUNT(*) as conto FROM portata WHERE portata.cod_portata="+posizione);
                    ctrl2.next();
                    if ((ctrl2.getInt("conto"))!=0){
                        stmt.executeUpdate("UPDATE portata SET cod_portata=cod_portata+1 WHERE cod_portata >="+posizione);
                    }
                    stmt.executeUpdate("INSERT INTO portata VALUES ('"+portata.toLowerCase()+"',"+posizione+")");
                }else{
                    return 0;//esiste già una portata con lo stesso nome
                }
            } catch (SQLException ex) {
                Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
            }
            return 1;
        }else{
            return 2;//I parametri sono null
        }
    }

    public int addPiatto (String piatto, String portata, Object[] ingredienti) throws NoSuchAlgorithmException{
                if (!piatto.isEmpty()&& !portata.isEmpty()){
            try {
                java.sql.Statement stmt = c.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
                ResultSet ctrl1=stmt.executeQuery("SELECT COUNT(*) as conto FROM piatto WHERE piatto.nome='"+piatto.toLowerCase()+"'");
                ctrl1.next();
                if (ctrl1.getInt("conto")==0){
                    MessageDigest m=MessageDigest.getInstance("MD5");
                    m.update(piatto.getBytes(),0,piatto.length());
                    String key=(m.digest()).toString();
                    stmt.executeUpdate("INSERT INTO piatto VALUES ('"+piatto.toLowerCase()+"','"+key+"')");
                    ResultSet cod_portata=stmt.executeQuery("SELECT portata.cod_portata FROM portata WHERE portata.nome='"+portata+"'");
                    cod_portata.next();
                    Integer cod_p=cod_portata.getInt("cod_portata");
                    stmt.executeUpdate("INSERT INTO categoria VALUES ('"+key+"',"+cod_p+")");
                    if (!(ingredienti.length==0)){
                        int i=0;
                        ResultSet ris;
                        for (i=0; i<ingredienti.length; i++){
                            ris=stmt.executeQuery("SELECT cod_ingrediente FROM ingrediente WHERE ingrediente.nome='"+ingredienti[i].toString().toLowerCase()+"'");
                            ris.next();
                            stmt.executeUpdate("INSERT INTO composizione VALUES('"+key+"','"+ris.getString("cod_ingrediente")+"')");
                        }
                    }
                }else{
                    return 0;// piatto con lo stesso nome
                }
            } catch (SQLException ex) {
                Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
            }
            return 1;
        }else{
            return 2;// Parametri null
        }
    }

    public Integer[] getPos () throws SQLException{
        java.sql.Statement stmt = c.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        ResultSet pos = stmt.executeQuery("SELECT cod_portata FROM portata ORDER BY cod_portata");
        ArrayList<Integer> ris = new ArrayList<Integer>();
        while (pos.next()){
            ris.add(pos.getInt("cod_portata"));
        }
        Integer[] risarray = new Integer[ris.size()+1];
        risarray=ris.toArray(risarray);
        return risarray;
    }

    public int addIngredienti(String ingrediente) throws SQLException, NoSuchAlgorithmException{
        if (!(ingrediente.isEmpty())){
            java.sql.Statement stmt = c.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
            String delims="[,]+";
            String[] ingredienti=ingrediente.split(delims);
            int size=ingredienti.length;
            int i=0;
            String temp, key;
            ResultSet ctrl1;
            MessageDigest m=MessageDigest.getInstance("MD5");
                for (i=0;i<size;i++){
                    temp=ingredienti[i].trim();
                    temp=temp.replaceAll(" {2,}", " ");
                    ctrl1=stmt.executeQuery("SELECT COUNT(*) as conto FROM ingrediente WHERE ingrediente.nome='"+temp.toLowerCase()+"'");
                    ctrl1.next();
                    if (ctrl1.getInt("conto")==0){
                        m.update(ingredienti[i].getBytes(),0,ingredienti[i].length());
                        key=(m.digest()).toString();
                        stmt.executeUpdate("INSERT INTO ingrediente VALUES ('"+temp.toLowerCase()+"','"+key+"')");
                    }else{
                        return 0;//ingrediente con lo stesso nome
                    }
                }
            return 1;
        }else{
            return 2;// Parametri null
        }
    }

    public String[] getIngredienti(String piatto/*chiave primaria*/) throws SQLException{
        java.sql.Statement stmt = c.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        ResultSet ingredienti;
        if (piatto==null){
            ingredienti = stmt.executeQuery("SELECT ingrediente.nome FROM ingrediente ORDER BY ingrediente.nome");
        }else{
            ingredienti = stmt.executeQuery("SELECT ingrediente.nome from ((ingrediente left join composizione on ingrediente.cod_ingrediente = composizione.cod_ingrediente) left join piatto on piatto.cod_piatto=composizione.cod_piatto) where piatto.nome ='"+piatto+"'  ORDER BY ingrediente.nome");
        }
        ArrayList<String> ris = new ArrayList<String>();
        while (ingredienti.next()){
            ris.add(ingredienti.getString("nome"));
        }
        String[] risarray = new String [ris.size()];
        risarray=ris.toArray(risarray);
        return risarray;
    }

        public int deletePortata (String nportata){
        int num = 0;
        int cportata;
        ResultSet piatti, piatto_categoria,codportata;

          try {
                java.sql.Statement stmt = c.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
                /*  Estraggo il codice della portata    */
                nportata = SQLString(nportata);
                codportata = stmt.executeQuery("SELECT cod_portata FROM portata WHERE nome='"+ nportata +"'");
                codportata.next();
                cportata = codportata.getInt("cod_portata");

                /* Verifico se ci sono piatti associati alla portata che si vuole eliminare*/
                piatti = stmt.executeQuery("SELECT COUNT(*) as conto FROM piatto LEFT JOIN categoria ON categoria.cod_piatto=piatto.cod_piatto WHERE categoria.cod_portata="+cportata);
                piatti.next();
                if(piatti.getInt("conto")!=0){   // se sono presenti li elimino
                    piatto_categoria = stmt.executeQuery("SELECT categoria.cod_piatto FROM categoria WHERE categoria.cod_portata="+cportata);
                    while(piatto_categoria.next()){
                        stmt.executeUpdate("DELETE FROM piatto WHERE piatto.cod_piatto='"+piatto_categoria.getString("cod_piatto")+"'");
                    }

                }

                /*      Elimino la portata      */
                stmt.executeUpdate("DELETE FROM portata WHERE portata.nome='"+ nportata +"'");

                /*  alla fine si aggiornano gli indici delle portate    */
                num = stmt.executeUpdate("UPDATE portata SET cod_portata=cod_portata-1 WHERE cod_portata >="+cportata);
            } catch (SQLException ex) {
                Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
            }
            return num;
    }

    public int deletePiatto (String npiatto){

          try {
                java.sql.Statement stmt = c.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
                /*      Eliminazione piatto     */
                npiatto = SQLString(npiatto);
                stmt.executeUpdate("DELETE FROM piatto WHERE piatto.nome='"+npiatto+"'");

            } catch (SQLException ex) {
                Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
            }
            return 1;
    }

    public int deleteIngrediente (String ingr){

          try {
                java.sql.Statement stmt = c.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
                /*      Eliminazione piatto     */
                ingr = SQLString(ingr);
                stmt.executeUpdate("DELETE FROM ingrediente WHERE ingrediente.nome='"+ingr+"'");

            } catch (SQLException ex) {
                Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
            }
            return 1;
    }

    public String SQLString(String s){
        char[] car = s.toCharArray();
        String s1="";
        for (int i=0; i <= car.length-1 ; i++){
            if (car[i] == '\'')
                s1+="\'\'";
            else s1+=car[i];
        }
        return s1;
    }

    
    
}